package czu.caohao.controller;

import czu.caohao.dao.DBServerRepository;
import czu.caohao.json.ListReturnJson;
import czu.caohao.json.SimpleReturnJson;
import czu.caohao.pojo.DBServer;
import czu.caohao.utils.SqlUtils;
import org.hibernate.criterion.Example;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RestController
@RequestMapping("/server")
public class DBServerController implements InitializingBean {

    /**
     * 当对象被初始化时执行
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        // 查询数据库中所有的dbserver,放入Map<integer,dbserver>中
        List<DBServer> allServer = dbServerRepository.findAll();
        Map<Integer,DBServer> serverMap = new HashMap<>(allServer.size());
        allServer.forEach((e)->serverMap.put(e.getId(),e));
        // 实例化sqlUtils
        sqlUtils = new SqlUtils(serverMap);
    }

    private ExecutorService executorService = Executors.newFixedThreadPool(1);

    @Autowired
    private DBServerRepository dbServerRepository;

    private SqlUtils sqlUtils;
    /**
     * 获得所有的已经添加的db服务器
     * @return
     */
    @PostMapping("/allServer")
    public ListReturnJson allServer(){

        Map<Integer, DBServer> allServerInfos = sqlUtils.getAllServerInfos();
        ListReturnJson listReturnJson = null;
        if(allServerInfos!=null){
            listReturnJson = new ListReturnJson(true,"查询成功");
            listReturnJson.setList(Arrays.asList(allServerInfos.values().toArray()));
        }else {
            listReturnJson = new ListReturnJson(false,"查询失败");
            listReturnJson.setList(null);
        }
        return listReturnJson;
    }

    @PostMapping("/testConn")
    public SimpleReturnJson testConn(DBServer server){
        String ip = server.getServerIp();
        Integer port = server.getServerPort();
        String username = server.getUsername();
        String pass = server.getPass();
        Connection conn = sqlUtils.getConn(ip, port, username, pass);
        boolean closed = true;

        try {
            if(conn == null){
                closed = true;
            }
            else {closed = conn.isClosed();};
        } catch (SQLException e) {
            closed = true;
        }
        // 测试完之后将该连接关闭
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(conn!=null&&!closed){
            return new SimpleReturnJson(true,"连接成功");
        }else {
            return new SimpleReturnJson(false,"无法连接");
        }
    }

    @PostMapping("/addNewServer")
    public SimpleReturnJson addNewServer(DBServer server){
        // 先判断这条记录在数据库中是否存在
        Integer id= dbServerRepository.getDBServerByIpAndPort(server.getServerIp(),server.getServerPort());
        if(id != null){
            return new SimpleReturnJson(false,"该ip和端口的服务器已存在");
        }
        // 向数据库中添加一条记录
        server.setServerStatus(DBServer.DBServerStatus.ONLINE_STATUS);
        server.setServerIdentity(DBServer.DBServerIdentity.MASTER);
        dbServerRepository.save(server);
        // 将数据库中的数据全部导出到data.sql中
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                resetDataFile();
            }
        });

        boolean result = sqlUtils.addServer(server);

        if(result){
            return new SimpleReturnJson(true,"添加成功");
        }else {
            return new SimpleReturnJson(false,"添加失败");
        }
    }

    public boolean resetDataFile(){
        List<DBServer> all = dbServerRepository.findAll();
        StringBuffer sb = new StringBuffer();

        for (DBServer server : all){
            String sql = sqlUtils.transferDbServerToSqlStatement(server);
            sb.append(sql);
        }
        // 先备份原来的data.sql文件
        Resource resource = new ClassPathResource("data.sql");
        Resource resourceBak = new ClassPathResource("data.bak");
        BufferedWriter dataBakWriter = null;
        BufferedWriter dataWriter = null;
        BufferedReader dataReader = null;
        try {
            File data = resource.getFile();
            File dataBak = resourceBak.getFile();
            // 将data.sql中数据被分到data.bak中
            dataBakWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(dataBak)));
            dataReader = new BufferedReader(new InputStreamReader(new FileInputStream(data)));
            StringBuffer origin = new StringBuffer();
            String tmp = null;
            while ((tmp = dataReader.readLine())!=null){
                origin.append(tmp).append("\n");
            }
            dataBakWriter.write(origin.toString());
            dataBakWriter.flush();

            // 将数据保存到data.sql文件中
            dataWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(data)));
            dataWriter.write(sb.toString());
            dataWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } finally {
            if(dataBakWriter!=null){
                try {
                    dataBakWriter.close();
                } catch (IOException e) {
                    return false;
                }
            }
            if(dataWriter!=null){
                try {
                    dataWriter.close();
                } catch (IOException e) {
                    return false;
                }
            }
        }
        return true;
    }


    /**
     * 删除某个server
     * @param id
     * @return
     */
    @PostMapping("/delete")
    public SimpleReturnJson delete(@RequestParam(value = "id",required = true) Integer id){
        // 先将sqlUtil中该节点相关信息删除
        sqlUtils.deleteServer(id);

        // 将该数据从数据库中删除
        Optional<DBServer> deletedServer = dbServerRepository.findById(id);
        if(deletedServer.isPresent()){
            dbServerRepository.deleteById(id);
            // 将删除之后的数据保存回文件
            resetDataFile();
        }
        return new SimpleReturnJson(true,"删除成功");
    }

    /**
     * 停止某个server的slave（停止与主服务器的同步）
     * @param id
     * @return
     */
    @PostMapping("/stopSlave")
    public SimpleReturnJson stopSlave(@RequestParam(value = "id",required = true) Integer id){
        boolean result = sqlUtils.stopSlave(id);
        if(result){
            return new SimpleReturnJson(true,"关闭成功");
        }else {
            return new SimpleReturnJson(false,"关闭失败");
        }
    }

    /**
     * 开启某个server与主服务器的同步
     * @param id
     * @return
     */
    @PostMapping("/startSlave")
    public SimpleReturnJson startSlave(@RequestParam(value = "id",required = true) Integer id){
        boolean result = sqlUtils.startSlave(id);
        if(result){
            return new SimpleReturnJson(true,"开启成功");
        }else {
            return new SimpleReturnJson(false,"开启失败");
        }
    }

}
